package com.yaorange.teaching.service.impl;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yaorange.common.core.utils.StringUtils;
import com.yaorange.teaching.bo.AddTeachingPlanBo;
import com.yaorange.teaching.bo.PreviewTeachingPlanBo;
import com.yaorange.teaching.domain.*;
import com.yaorange.teaching.mapper.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import com.yaorange.teaching.service.IYaTeachingPlanService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

/**
 * 教学计划(课)Service业务层处理
 *
 * @author ruoyi
 * @date 2024-11-20
 */
@Service
public class YaTeachingPlanServiceImpl extends ServiceImpl<YaTeachingPlanMapper,YaTeachingPlan> implements IYaTeachingPlanService
{
    public static final String RESTDAY = ":restday";
    public static final String SELFSTUDYDAY = ":selfstudyday";
    public static final String WORKDAY = ":workday";
    public static final String REST_DAY = "休息";
    public static final String SELF_STUDY_DAY = "自习";
    @Autowired
    private YaTeachingPlanMapper yaTeachingPlanMapper;
    @Autowired
    private YaClassMapper yaClassMapper;
    @Autowired
    private YaCourseDesignDetailMapper yaCourseDesignDetailMapper;
    @Autowired
    private YaHolidayMapper yaHolidayMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    /**
     * 查询教学计划(课)
     *
     * @param id 教学计划(课)主键
     * @return 教学计划(课)
     */
    @Override
    public YaTeachingPlan selectYaTeachingPlanById(Long id)
    {
        return yaTeachingPlanMapper.selectYaTeachingPlanById(id);
    }

    /**
     * 查询教学计划(课)列表
     *
     * @param yaTeachingPlan 教学计划(课)
     * @param classNames
     * @return 教学计划(课)
     */
    @Override
    public List<YaTeachingPlan> selectYaTeachingPlanList(YaTeachingPlan yaTeachingPlan, List<String> classNames)
    {
        return yaTeachingPlanMapper.selectYaTeachingPlanList(yaTeachingPlan,classNames);
    }

    /**
     * 新增教学计划(课)
     *
     * @param yaTeachingPlanBo 教学计划(课)
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertYaTeachingPlan(AddTeachingPlanBo yaTeachingPlanBo)
    {
        //删除之前的课表
        Integer stage = yaTeachingPlanBo.getStage();
        String className = yaTeachingPlanBo.getClassName();
        LambdaQueryWrapper<YaTeachingPlan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(YaTeachingPlan::getStage, stage);
        queryWrapper.eq(YaTeachingPlan::getClassName, className);
        yaTeachingPlanMapper.delete(queryWrapper);
        return saveBatch(yaTeachingPlanBo.getTeachingPlanList(), 100)?1:0;
    }

    /**
     * 修改教学计划(课)
     *
     * @param yaTeachingPlan 教学计划(课)
     * @return 结果
     */
    @Override
    public int updateYaTeachingPlan(YaTeachingPlan yaTeachingPlan)
    {
        return yaTeachingPlanMapper.updateYaTeachingPlan(yaTeachingPlan);
    }

    /**
     * 批量删除教学计划(课)
     *
     * @param ids 需要删除的教学计划(课)主键
     * @return 结果
     */
    @Override
    public int deleteYaTeachingPlanByIds(Long[] ids)
    {
        return yaTeachingPlanMapper.deleteYaTeachingPlanByIds(ids);
    }

    /**
     * 删除教学计划(课)信息
     *
     * @param id 教学计划(课)主键
     * @return 结果
     */
    @Override
    public int deleteYaTeachingPlanById(Long id)
    {
        return yaTeachingPlanMapper.deleteYaTeachingPlanById(id);
    }

    @Override
    @Transactional(readOnly = true)
    public List<YaTeachingPlan> selectYaTeachingPlanList(String className, Integer stage) {
        QueryWrapper<YaTeachingPlan> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq(StringUtils.isNotEmpty(className),"class_name", className);
        objectQueryWrapper.eq("stage", stage);
        return yaTeachingPlanMapper.selectList(objectQueryWrapper);
    }

    @Override
    @Transactional(readOnly = true)
    public List<YaTeachingPlan> preview(PreviewTeachingPlanBo previewTeachingPlanBo) {
        String className = previewTeachingPlanBo.getClassName();
        //获取到班级正常休息日和自习日
        QueryWrapper<YaClass> yaClassQueryWrapper = new QueryWrapper<>();
        yaClassQueryWrapper.eq("class_name", className);
        YaClass yaClass = yaClassMapper.selectOne(yaClassQueryWrapper);
        Integer restDay = yaClass.getRestDay();
        Integer selfStudyDay = yaClass.getSelfStudyDay();
        //查询指定阶段的所有课程设计
        Integer stage = previewTeachingPlanBo.getStage();
        Long courseId = previewTeachingPlanBo.getCourseId();
        LambdaQueryWrapper<YaCourseDesignDetail> yaCourseDesignQueryWrapper = new LambdaQueryWrapper<>();
        yaCourseDesignQueryWrapper.eq(YaCourseDesignDetail::getStage, stage);
        yaCourseDesignQueryWrapper.eq(YaCourseDesignDetail::getCourseId, courseId);
        List<YaCourseDesignDetail> courseDesignList = yaCourseDesignDetailMapper.selectList(yaCourseDesignQueryWrapper);
        //查询起始日期以后的所有节假日
        LambdaQueryWrapper<YaHoliday> yaHolidayLambdaQueryWrapper = new LambdaQueryWrapper<>();
        yaHolidayLambdaQueryWrapper.ge(YaHoliday::getDate, previewTeachingPlanBo.getBeginDate());
        Map<String, String> holidayMap = yaHolidayMapper.selectList(yaHolidayLambdaQueryWrapper).stream().collect(Collectors.toMap(YaHoliday::getDate, YaHoliday::getDescription));
        //获取到班级特殊 休息日 和 自习日，上课日
        Map<Object, Object> restDayMap = stringRedisTemplate.opsForHash().entries(className + RESTDAY);
        Map<Object, Object> selfStudyDayMap = stringRedisTemplate.opsForHash().entries(className + SELFSTUDYDAY);
        Map<Object, Object> workDayMap = stringRedisTemplate.opsForHash().entries(className + WORKDAY);
        int size = courseDesignList.size();
        int day = 1;
        //从起始日期开始遍历
        LocalDate currentDay = LocalDate.parse(previewTeachingPlanBo.getBeginDate());
        List<YaTeachingPlan> result = new ArrayList<>(size<<1);
        do{
            YaTeachingPlan yaTeachingPlan = new YaTeachingPlan();
            String currentDayString = currentDay.toString();
            //公共字段
            yaTeachingPlan.setDate(currentDayString);
            yaTeachingPlan.setWeekday(currentDay.getDayOfWeek().getValue());
            yaTeachingPlan.setClassesId(yaClass.getId());
            yaTeachingPlan.setStage(stage);
            yaTeachingPlan.setClassName(className);
            yaTeachingPlan.setCourseId(courseId);

            //判断是否国家法定节假日
            if (holidayMap.containsKey(currentDayString)) {
                yaTeachingPlan.setCourseContent(holidayMap.get(currentDayString));
            }
            //判断是否班级特殊自习/休息
            else if(restDayMap.containsKey(currentDayString)){
                yaTeachingPlan.setCourseContent(REST_DAY);
            }
            else if(selfStudyDayMap.containsKey(currentDayString)){
                yaTeachingPlan.setCourseContent(SELF_STUDY_DAY);
            }
            //判断是否班级正常休息 并且 不在班级特殊上课日中
            else if(yaTeachingPlan.getWeekday().equals(restDay)&&!workDayMap.containsKey(currentDayString)){
                yaTeachingPlan.setCourseContent(REST_DAY);
            }
            //判断是否班级正常自习 并且 不在班级特殊上课日中
            else if(yaTeachingPlan.getWeekday().equals(selfStudyDay)&&!workDayMap.containsKey(currentDayString)){
                yaTeachingPlan.setCourseContent(SELF_STUDY_DAY);
            }
            //正常上课
            else {
                YaCourseDesignDetail yaCourseDesign = courseDesignList.get(day - 1);
                yaTeachingPlan.setCourseContent(yaCourseDesign.getCourseContent());
                yaTeachingPlan.setCourseDesignDetailId(yaCourseDesign.getId());
                yaTeachingPlan.setDay(day++);
            }
            //获取下一天
            currentDay = currentDay.plusDays(1);
            //加入课表
            result.add(yaTeachingPlan);
        }while (day<=size);

        //返回预览课表
        return result;
    }

    @Override
    public void addHoliday(PreviewTeachingPlanBo previewTeachingPlanBo) {
        String className = previewTeachingPlanBo.getClassName();
        //根据类型新增到对应的非上课日集合
        String type = previewTeachingPlanBo.getType();
        String date = previewTeachingPlanBo.getDate();
        if (REST_DAY.equals(type)) {
            stringRedisTemplate.opsForHash().put(className + RESTDAY, date, type);
        } else {
            stringRedisTemplate.opsForHash().put(className + SELFSTUDYDAY, date, type);
        }

        //删除上课日集合中的数据
        stringRedisTemplate.opsForHash().delete(className+WORKDAY,date);
    }

    @Override
    public void addWorkday(PreviewTeachingPlanBo previewTeachingPlanBo) {
        String className = previewTeachingPlanBo.getClassName();
        String date = previewTeachingPlanBo.getDate();
        //新增到工作日集合
        stringRedisTemplate.opsForHash().put(className + WORKDAY, date, WORKDAY);
        //从两个非工作日中删除
        stringRedisTemplate.opsForHash().delete(className+RESTDAY,date);
        stringRedisTemplate.opsForHash().delete(className+SELFSTUDYDAY,date);
    }
}
